package comp.wxapi.service;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceApacheHttpImpl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import comp.wxapi.bean.BaseConfigBean;
import comp.wxapi.constants.Constants;
import comp.wxapi.utils.ConfigUtils;
import comp.wxapi.utils.StorageServiceUtils;
import comp.wxapi.vo.WXConfig;
import me.chanjar.weixin.mp.api.WxMpService;
import weixin.popular.api.API;

public abstract class WxAbstractBaseService implements WxBaseService {

	public static ConcurrentHashMap<String, String> APPID_SECRET_CONFIG = new ConcurrentHashMap<String, String>();

	public static final Logger logger = LoggerFactory.getLogger(WxAbstractBaseService.class);

	@Override
	public BaseConfigBean getBaseConfig(String key, String group) {
		printAllHeaders();
		BaseConfigBean configBean = new BaseConfigBean();
		configBean.setOpenid(getHeader(Constants.HEADER_OPENID));
		configBean.setOpenid(getHeader("X-Session-SessionKey"));
		List<WXConfig> configs = ConfigUtils.getConfigsLikeKey(key, group);
		setConfigBean(configs, configBean);
		logger.info("config={}", JSONObject.toJSONString(configBean));
		return configBean;
	}

	@Override
	public String getAccessToken(String appid) {
		return null;
	}

	@Override
	public String getAccessToken(String appid, String appsecret) {
		String accessToken = "";
		if (StringUtils.isNotEmpty(appid) && StringUtils.isNotEmpty(appsecret)) {
			APPID_SECRET_CONFIG.put(appid, appsecret);
			accessToken = API.accessToken(appid);
		}
		return accessToken;
	}

	@Override
	public WxMaService wxMaService(BaseConfigBean configBean) {
		return null;
	}

	@Override
	public WxMpService wxMpService(BaseConfigBean baseConfigBean) {
		return null;
	}

	@Override
	public BaseConfigBean getBaseConfig() {
		return null;
	}

	@Override
	public WxPayConfig getPayConfig(boolean isRefund) {

		return null;
	}

	@Override
	public WxPayService getWxpayService(WxPayConfig wxPayConfig) {
		WxPayService wxPayService = new WxPayServiceApacheHttpImpl();
		wxPayService.setConfig(wxPayConfig);
		return wxPayService;
	}

	@Override
	public WxPayConfig getPayConfig(boolean isRefund, String key, String group) {
		printAllHeaders();
		WxPayConfig wxPayConfig = new WxPayConfig();
		List<WXConfig> configs = ConfigUtils.getConfigsLikeKey(key, group);
		logger.info("config={}", JSON.toJSON(configs));
		setWxPayConfig(wxPayConfig, configs,isRefund);
		// 支付通知地址，默认首先通知到组件内部，验签解密等动作成功后才通知到对应的应用
		if (isRefund) {
			if (key.equals(Constants.MP_KEY)) {
				wxPayConfig.setNotifyUrl(host() + Constants.MP_DEFUALT_REFUND_NOFITY_HOST);
			}
			if (key.equals(Constants.MINIAPP_KEY)) {
				wxPayConfig.setNotifyUrl(host() + Constants.MINIAPP_DEFUALT_REFUND_NOFITY_HOST);
			}
		} else {
			if (key.equals(Constants.MP_KEY)) {
				wxPayConfig.setNotifyUrl(host() + Constants.MP_DEFUALT_NOFITY_HOST);
			}
			if (key.equals(Constants.MINIAPP_KEY)) {
				wxPayConfig.setNotifyUrl(host() + Constants.MINIAPP_DEFUALT_NOFITY_HOST);
			}
		}
		logger.info("wxPayConfig={}", JSON.toJSON(wxPayConfig));
		return wxPayConfig;
	}

	/**
	 * 获取HttpServletRequest对象
	 * 
	 * @return
	 */
	public HttpServletRequest getRequest() {
		ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		return sra.getRequest();
	}

	/**
	 * 获取HttpServletResponse对象
	 * 
	 * @return
	 */
	public HttpServletResponse getResponse() {
		ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		return sra.getResponse();
	}

	/**
	 * 获取当前应用域名
	 * 
	 * @return
	 */
	public String host() {
		HttpServletRequest request = getRequest();
		String url = request.getScheme() + "://" + request.getServerName();
		if (request.getServerPort() != 80 && request.getServerPort() != 443 ) {
			url += ":" + request.getServerPort();
		}
		return url;
	}

	public String getCookie() {
		HttpServletRequest request = getRequest();
		Cookie[] cookies = request.getCookies();
		StringBuilder builder = new StringBuilder();
		int len = cookies.length;
		for(int i=0;i<len;i++) {
			builder.append(cookies[i].getName())
					.append("=")
					.append(cookies[i].getValue());
			if(i < len-1) {
				builder.append(";");
			}
		}
		return builder.toString();
	}
	
	@Override
	public String getHeader(String key) {
		
		return getRequest().getHeader(key);
	}
	
	public void printAllHeaders() {
		HttpServletRequest request = getRequest();
		Enumeration<String> headerNames = request.getHeaderNames();
		List<String> headers = new ArrayList<String>();
		while (headerNames.hasMoreElements()) {
			String name = headerNames.nextElement();
			String head = name+"="+request.getHeader(name);
			headers.add(head);
		}
		logger.info("AllHeaders={}",JSONObject.toJSONString(headers));
	}
	
	protected void setConfigBean(List<WXConfig> configs,BaseConfigBean configBean) {
		if(configs != null && !configs.isEmpty()) {
			for (WXConfig config : configs) {
				String configKey = config.getFkey();
				String value = config.getFvalue();
				if (configKey.endsWith(Constants.APPID_KEY)) {
					configBean.setAppid(value);
					continue;
				}
				if (configKey.endsWith(Constants.APP_SECRET_KEY)) {
					configBean.setAppsecret(value);
					continue;
				}
				if (configKey.endsWith(Constants.TOKEN_KEY)) {
					configBean.setToken(value);
					continue;
				}
				if (configKey.endsWith(Constants.ENCODING_AES_KEY_KEY)) {
					configBean.setEncodingAESKey(value);
					continue;
				}
				if (configKey.endsWith(Constants.NOTIFY_URL_KEY)) {
					configBean.setNotifyUrl(value);
					continue;
				}
				if (configKey.endsWith(Constants.PAY_NOTIFY_URL_KEY)) {
					configBean.setPayNotifyUrl(value);
					continue;
				}
				if (configKey.endsWith(Constants.PAY_REFUND_NOTIFY_URL_KEY)) {
					configBean.setRefundNotifyUrl(value);
					continue;
				}
			}
		}
	}
	
	public void setWxPayConfig(WxPayConfig wxPayConfig,List<WXConfig> configs,boolean isRefund) {
		if(configs != null && !configs.isEmpty()) {
			for (WXConfig config : configs) {
				String cKey = config.getFkey();
				String value = config.getFvalue();
				if (cKey.endsWith(Constants.APPID_KEY)) {
					wxPayConfig.setAppId(value);
					continue;
				}
				if (cKey.endsWith(Constants.PAY_MCHID_KEY)) {
					wxPayConfig.setMchId(value);
					continue;
				}
				if (cKey.endsWith(Constants.PAY_MCHKEY_KEY)) {
					wxPayConfig.setMchKey(value);
					continue;
				}
				if (cKey.endsWith(Constants.PAY_API_CLIENT_CERT_PATH_KEY) && isRefund) {
					String keyPath = StorageServiceUtils.getApiClientCertPath(value, host());
					wxPayConfig.setKeyPath(keyPath);
					continue;
				}
			}
		}
	}

}
